#![cfg_attr(feature = "axstd", no_std)]
#![cfg_attr(feature = "axstd", no_main)]

#[cfg(all(feature = "axstd", feature = "std"))]
compile_error!("features `axstd` and `std` cannot be enabled together");

#[cfg(feature = "axstd")]
#[macro_use]
extern crate axstd;

#[cfg(feature = "axstd")]
extern crate alloc;

use gpio_cmd::{self, Command as GpioCommand};
use sbox_proto::{gpio as gpio_proto, pmu as pmu_proto, timer as timer_proto};

const GPIO3_BANK: usize = 3;
const BLUE_LED_PIN: u8 = 6;
const GREEN_LED_PIN: u8 = 9;

const BUTTON_BANK: usize = 1;
const BUTTON_PIN: u8 = 4;
const BUTTON_POLL_SPIN_LOOPS: usize = 1_000;

const VCCIO1_4_IOC_BASE: usize = 0xFD5F9000;
const GPIO1A_PULL_OFFSET: usize = 0x0110;
const PULL_PINS_PER_REG: u32 = 8;
const PULL_BITS_PER_PIN: u32 = 2;
const PULL_UP_CODE: u32 = 0b11;

#[cfg(not(feature = "axstd"))]
const VCCIO_MMAP_LENGTH: usize = 0x1000;
#[cfg(not(feature = "axstd"))]
const DEV_MEM_PATH: &str = "/dev/mem";

const TIMER_CHANNEL_BLINK: u32 = 0;
const TIMER_CHANNEL_BREATH: u32 = 1;
const TIMER_FREQ_HZ: u64 = 24_000_000;
const SOFT_PWM_FREQ_HZ: u64 = 1000;
const BREATH_PERIOD_US: u64 = 1_000_000 / SOFT_PWM_FREQ_HZ;
const COUNTDOWN_SPIN_LOOPS: usize = 10_000_000;

const GPIO_DEVICE_PATH: &str = "/dev/rk3588-gpio";
const TIMER_DEVICE_PATH: &str = "/dev/rk3588-timer";
const PMU_DEVICE_PATH: &str = "/dev/rk3588-pmu";

#[cfg(feature = "axstd")]
#[unsafe(no_mangle)]
fn main() {
    runtime::run();
}

#[cfg(not(feature = "axstd"))]
fn main() {
    runtime::run();
}

#[cfg(feature = "axstd")]
mod runtime {
    use alloc::{borrow::ToOwned, string::ToString, vec::Vec};
    use core::{
        ffi::{c_char, c_int, c_ulong, c_void},
        str,
    };

    use axstd::{
        env, fs,
        io::{self, prelude::*},
        string::String,
        thread,
        time::{Duration, Instant},
    };

    use super::*;

    include!("runtime_shared.rs");
}

#[cfg(not(feature = "axstd"))]
mod runtime {
    use core::{
        ffi::{c_char, c_int, c_ulong, c_void},
        str,
    };
    #[cfg(target_os = "none")]
    use std::{borrow::ToOwned, fs};
    use std::{
        env,
        fs::OpenOptions,
        io::{self, ErrorKind, prelude::*},
        os::unix::io::AsRawFd,
        string::{String, ToString},
        sync::mpsc::{self, TryRecvError},
        thread,
        time::{Duration, Instant},
        vec::Vec,
    };

    use super::*;

    include!("runtime_shared.rs");
}
